#ifndef __RINGQUEUE_HPP__
#define __RINGQUEUE_HPP__

#include <pthread.h>
#include <vector>
#include <semaphore.h>


template<typename T>
class RingQueue
{
public:
    RingQueue(int maxcap) : _maxcap(maxcap), _rq(maxcap)
    {
        pthread_mutex_init(&_producer_mutex, nullptr);
        pthread_mutex_init(&_consumer_mutex, nullptr);
        sem_init(&_producer_sem, 0, maxcap); //生产者关心的是空间
        sem_init(&_consumer_sem, 0, 0); //消费者关心的是数据
        _producer_step = _consumer_step = 0;
    }

    void push(T& in) //生产者调用
    {
        //申请信号量预定资源
        sem_wait(&_producer_sem);

        pthread_mutex_lock(&_producer_mutex);
        //将数据放入到队列中
        _rq[_producer_step] = in;
        _producer_step = (_producer_step+1) % _maxcap;
        pthread_mutex_unlock(&_producer_mutex);

        //释放消费者信号量
        sem_post(&_consumer_sem);
    }


    void pop(T& out) //消费者调用
    {
        //申请信号量预定资源
        sem_wait(&_consumer_sem);

        pthread_mutex_lock(&_consumer_mutex);
        //获取数据
        out = _rq[_consumer_step];
        _consumer_step = (_consumer_step+1) % _maxcap;
        pthread_mutex_unlock(&_consumer_mutex);


        //释放生产者信号量
        sem_post(&_producer_sem);
    }


    ~RingQueue()
    {
        pthread_mutex_destroy(&_producer_mutex);
        pthread_mutex_destroy(&_consumer_mutex);
        sem_destroy(&_producer_sem);
        sem_destroy(&_consumer_sem);
    }
private:
    std::vector<T> _rq; //模拟循环队列
    int _maxcap; //循环队列的大小

    int _producer_step; //生产者步伐（队尾指针）
    int _consumer_step; //消费者步伐（队头指针）

    pthread_mutex_t _producer_mutex; //保护生产者步伐的锁
    pthread_mutex_t _consumer_mutex; //保护消费者步伐的锁


    sem_t _producer_sem; //生产者信号量
    sem_t _consumer_sem; //消费者信号量
};


#endif